import { EventManagerService } from './../../../../../../services/event-manager.service';
import Grid from 'muuri';
import { NzMessageService } from 'ng-zorro-antd/message';
import { CodeGroupItem, OrgCodeItem, OrgCodeItemType } from '../models';
import { Component, OnInit, AfterViewInit, ComponentRef, ElementRef, Renderer2, ViewChild, Input, Output, EventEmitter, ChangeDetectorRef } from '@angular/core';
import { AutoCodeInputComponent } from '../auto-code-input/auto-code-input.component';
import { DateCodeInputComponent } from '../date-code-input/date-code-input.component';
import { GroupCodeInputComponent } from '../group-code-input/group-code-input.component';
import { SeparatorCodeInputComponent } from '../separator-code-input/separator-code-input.component';
import { SettledCodeInputComponent } from '../settled-code-input/settled-code-input.component';
import { Tools } from 'src/app/common/tools/tools';
import { MuuriComponentService } from '../../../../../../services/muuri-component.service';

@Component({
  selector: 'zepride-org-code-item-panel',
  templateUrl: './org-code-item-panel.component.html',
  styleUrls: ['./org-code-item-panel.component.less']
})
export class OrgCodeItemPanelComponent implements OnInit, AfterViewInit {
  @ViewChild('dragPanel') dragPanel: ElementRef<HTMLDivElement>;
  @Input() codeItemList: OrgCodeItem[] = [];
  @Input() onDelete: { key?: string; handle; };
  @Input() groupId?: string;
  @Input() rowId?: string;
  showTitle: boolean = true;
  @Input() codeName: string = '编码名称';
  @Output() codeNameChange = new EventEmitter();
  @Output() onAllItemDelete = new EventEmitter();
  showInput: boolean;

  private grid: Grid;

  constructor(
    private message: NzMessageService,
    private muuriComponentService: MuuriComponentService,
    private render: Renderer2,
    private eventSvr: EventManagerService,
    private changeRef: ChangeDetectorRef
  ) { }

  ngOnInit(): void {
    if (this.onDelete) {
      this.onDelete.handle = this.onDeleteHandle.bind(this);
    }
  }

  codeNameInputChange() {
    this.codeNameChange.emit(this.codeName);
  }

  ngAfterViewInit(): void {
    this.grid = new Grid(this.dragPanel.nativeElement, {
      dragEnabled: true,
      layoutOnResize: 200,
      layout: {
        fillGaps: false,
        horizontal: false,
        alignRight: false,
        alignBottom: false,
        rounding: false
      },
    });

    this.grid.on('dragEnd', (currentOrder, previousOrder) => {
      this.reOrderByList();
    });

    if (this.codeItemList && this.codeItemList.length) {
      for (let item of this.codeItemList) {
        if (item.type == OrgCodeItemType.Group) {
          this.showTitle = false;
          this.changeRef.detectChanges();
          let com = this.renderOrgCodeItem(item);
          com.instance.onResize = this.refreshOrgItems.bind(this);
          com.instance.onDelOrgCodeItemHandle = (args) => {
            this.showTitle = true;
            this.onDelOrgCodeItem(args);
          }
          item.com = com;
        }
        else if (item.type == OrgCodeItemType.Settled) {
          let com = this.renderOrgCodeItem(item);
          com.instance.onAddItemHandle = this.addOrgItemElement.bind(this);
          com.instance.onAddGroupItemHandle = this.addOrgItemGroupItem.bind(this);
          item.com = com;
        }
        else {
          item = this.bindOrgItemElement(item);
        }
      }


      setTimeout(() => {
        this.eventSvr.callEvents('groupBoxResize', null);
      }, 200);

    }

    this.refreshOrgItems();
  }

  onDragOver(event: DragEvent) {
    event.preventDefault();
  }

  onDrop(event: DragEvent) {
    event.preventDefault();
  }

  onDeleteHandle() {
    let groupItem = this.codeItemList.find(x => x.type == OrgCodeItemType.Group);
    if (groupItem) {
      groupItem.com.instance.onDelete();
    }
  }

  addOrgItemGroupItem() {
    let groupItem = this.codeItemList.find(x => x.isGroup);
    if (groupItem) {
      let item = {
        parentId: groupItem.id,
        rowId: Tools.GetGuid(),
        codeName: this.codeName,
        list: [this.getNewCodeItem(OrgCodeItemType.Auto)],
        onSaveEvent: {
          key: Tools.GetGuid()
        }
      }
      groupItem.com.instance.orgItem.codeGroupItems.push(item);
    }
    else {
      groupItem = this.getNewCodeItem(OrgCodeItemType.Group);
      groupItem.isGroup = true;
      groupItem.codeGroupItems = [
        {
          codeName: this.codeName,
          rowId: Tools.GetGuid(),
          parentId: groupItem.id,
          list: [this.getNewCodeItem(OrgCodeItemType.Auto)],
        }
      ];

      let com = this.renderOrgCodeItem(groupItem, 0);
      com.instance.onResize = this.refreshOrgItems.bind(this);
      com.instance.onDelOrgCodeItemHandle = (args) => {
        this.showTitle = true;
        this.onDelOrgCodeItem(args);
      }
      groupItem.com = com;
      this.codeItemList.unshift(groupItem);
    }

    this.eventSvr.callEvents('groupBoxResize', null);

    this.showTitle = false;
    this.refreshOrgItems();
  }

  addOrgItemElement(type: OrgCodeItemType = OrgCodeItemType.Auto) {
    if (this.codeItemList.length >= 6) {
      this.message.create('error', `最大只能添加6个组件！`);
      return;
    }
    let item = this.getNewCodeItem(<any>type);
    item = this.bindOrgItemElement(item);
    this.codeItemList.push(item);
    this.refreshOrgItems();
  }

  bindOrgItemElement(item: OrgCodeItem) {
    let com = this.renderOrgCodeItem(item);
    com.instance.onAddItemHandle = this.addOrgItemElement.bind(this);
    com.instance.onDelOrgCodeItemHandle = this.onDelOrgCodeItem.bind(this);
    item.com = com;

    return item;
  }

  private renderOrgCodeItem(item: OrgCodeItem, index?: number) {
    const element = this.render.createElement('div') as HTMLElement;
    element.classList.add('item');
    if (item.type == OrgCodeItemType.Separator) {
      element.style.width = "70px";
    }
    else if (item.type == OrgCodeItemType.Group) {
      element.style.width = "270px";
      element.style.margin = "0px";
      element.style.height = "100px";
      element.id = "group-" + item.id;
    }

    element.dataset.id = item.id;
    const div = this.render.createElement('div');
    div.classList.add('item-content');
    element.appendChild(div);
    let i = this.grid.getItems();
    if (index == undefined) {
      index = i.length;
    }
    this.grid.add(element, { index });
    let com: ComponentRef<any>;

    if (item.type == OrgCodeItemType.Auto) {
      com = this.muuriComponentService.renderComponentToDom(div, AutoCodeInputComponent);
    }
    else if (item.type == OrgCodeItemType.Separator) {
      com = this.muuriComponentService.renderComponentToDom(div, SeparatorCodeInputComponent);
    }
    else if (item.type == OrgCodeItemType.Date) {
      com = this.muuriComponentService.renderComponentToDom(div, DateCodeInputComponent);
    }
    else if (item.type == OrgCodeItemType.Group) {
      com = this.muuriComponentService.renderComponentToDom(div, GroupCodeInputComponent);
    }
    else if (item.type == OrgCodeItemType.Settled) {
      com = this.muuriComponentService.renderComponentToDom(div, SettledCodeInputComponent);
    }
    com.instance.orgItem = item;

    return com;
  }

  private refreshOrgItems(args?) {
    setTimeout(() => {
      this.grid.refreshItems().layout();
    }, 300);

    for (let item of this.codeItemList) {
      if (item.com) {
        item.com.instance.onRefreshOrgItems && item.com.instance.onRefreshOrgItems();
      }
    }
  }

  onDelOrgCodeItem(orgItem: OrgCodeItem) {
    const items = this.grid.getItems();
    const target = items.find(item => {
      const result = item.getElement().dataset.id;
      return result === orgItem.id;
    });

    this.grid.remove([target], { removeElements: true });

    let index = this.codeItemList.findIndex(x => x.id == orgItem.id);
    if (index > -1) {
      this.codeItemList.splice(index, 1);
    }

    this.refreshOrgItems();

    if (this.codeItemList.length == 0) {
      this.onAllItemDelete.emit();
    }
  }

  reOrderByList() {
    let items = this.grid.getItems();
    let idList = items.map(x => x.getElement().dataset.id);

    for (let index = 0; index < idList.length; index++) {
      let i = this.codeItemList.findIndex(x => x.id == idList[index]);
      if (i !== index) {
        let tmp = this.codeItemList[i];
        this.codeItemList[i] = this.codeItemList[index];
        this.codeItemList[index] = tmp;
      }
      else {
        continue;
      }
    }
  }

  getNewCodeItem(type: OrgCodeItemType): OrgCodeItem {
    let obj: OrgCodeItem = {
      id: Tools.GetGuid(),
      type,
      value: ''
    };
    if (this.groupId) {
      obj.groupId = this.groupId;
    }
    if (this.rowId) {
      obj.rowId = this.rowId;
    }

    if (type == OrgCodeItemType.Settled) {
      obj.value = '001';
      obj.canReset = true;
      obj.codeBit = 3;
      obj.resetRule = 'month';
      obj.incrementSeed = 1;
    }
    else if (type == OrgCodeItemType.Separator) {
      obj.value = '+';
    }
    else if (type == OrgCodeItemType.Date) {
      let t = new Date();
      obj.value = t.getFullYear() + "" + (t.getMonth() + 1) + "" + t.getDate();
      obj.separatorChar = "";
      obj.showDay = obj.showMonth = obj.showYear = true;
    }

    return obj;
  }

  inputBlur() {
    this.showInput = false;
  }

  editCodeName() {
    this.showInput = true;
  }
}
